#ifndef GRAPH_H
#define GRAPH_H

#include <QWidget>
#include <unordered_map>
#include <unordered_set>
#include "splinecurve.h"


class Graph : public QWidget
{
    Q_OBJECT
public:
    explicit Graph(QWidget *parent = nullptr);

    void moveTo(qreal x, qreal y);
    int unitSpace() const;
    qreal unit() const;
    QPointF start() const;

    QString addCurve(const QString& name);
    void deleteCurve(const QString& = "");
    void clearSelect(const QString& = "");
    void selectCurve(const QString& id);
    bool hasSelectPoint();

    QString curveName(const QString& id) const;
    QColor curveColor(const QString& id) const;

    void setEditingCurve(const QString &id);
private:
    QPoint transformBack(const QPointF& pt) const;   //显示坐标转化为像素坐标
    QPointF transformTo(const QPoint& pt) const;     //像素坐标转化为计算坐标

    void paintGrid();
    void paintCurves();
    void paintSelectRect();
    void paintKeyPoint(const SplinePoint::ptr& sp);
    void paintCurve(const SplineCurve::ptr& curve);

    bool isInViewRect(const QPointF& pt) const;
    void selectPoints();
    void movePoints(QPointF point);


private:
    int m_unitSpace = 40;    //单位之间的空间
    qreal m_unit = 0.1;
    QPointF m_start = {0.0, 0.0};
    QPoint m_mousePosition;
    QPoint m_mousePressPosition;
    Qt::MouseButtons m_mouseBtn = Qt::NoButton;
    int m_key = Qt::Key_unknown;
    QRect m_selectRect; //选择区域

    std::unordered_map<QString, SplineCurve::ptr> m_curves;
    std::unordered_set<QString> m_activeCurve;
    QString m_editingCurveId;


    QMenu *m_pMenu;
    QAction *m_actAddKey;
    QAction *m_actDeleteKey;
    QActionGroup *m_grpTangentMode;
    QAction *m_actLinear;
    QAction *m_actConstant;
    QAction *m_actWeighted;
    QAction *m_actAuto;
    QAction *m_actUser;
    QAction *m_actBreak;
public slots:
    void changedPosition(QPointF position);
    void onAddKey();
    void onDeleteKey();
    void onTangentModeSelected(QAction* action);
signals:
    void selectPoint(QPointF point);
    void movePoint(QPointF offset);
    void hasSelectedPoint(bool has);
    void startPositionChanged(QPointF point);
    void zoomChanged(int space, qreal unit);
    // QWidget interface
protected:
    void paintEvent(QPaintEvent *event);
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void wheelEvent(QWheelEvent *event);
    void keyPressEvent(QKeyEvent *event);
    void keyReleaseEvent(QKeyEvent *event);
    void contextMenuEvent(QContextMenuEvent *event);
};

#endif // GRAPH_H
